<%
/*
  Draws an SVG diagram to display an interface's inheritance chain

  $0 - Interface name (defaults to the interface page the macro is called on)

  Test pages

    - http://localhost:3000/en-US/docs/Web/API/SVGTextPositioningElement
    - http://localhost:3000/en-US/docs/Web/API/WheelEvent
    - http://localhost:3000/en-US/docs/Web/API/USB/connect_event
    - http://localhost:3000/en-US/docs/Web/API/SVGTSpanElement
*/

const data = web.getJSONData("InterfaceData")[0];
const href = `/${env.locale}/docs/Web/API/`;
const mainInterfaceName = $0 || env.slug.replace('Web/API/','').split('/')[0];

let height = 40;
let xpos = 0;
let ypos = 0;
let left = 0;
let right = 0;

let inheritanceChain = [mainInterfaceName];
let inh = data[mainInterfaceName] != undefined ? data[mainInterfaceName].inh : '';

function getInheritance(inh) {
  if (inh !== '') {
    inheritanceChain.unshift(inh);
    if (data[inh]) {
        inh = data[inh].inh;
        getInheritance(inh);
    }
  }
}
getInheritance(inh);

function rectWithText(x, y, fill, interfaceName, reverse) {
  const rectWidth = calculateRectWidth(interfaceName);
  if (reverse) x -= rectWidth;
  return `
  <a style="text-decoration: none;" xlink:href="${href+interfaceName}">
    <rect x="${x}" y="${y}" width="${rectWidth}" height="25" fill="${fill}" stroke="#D4DDE4" stroke-width="2px" />
    <text x="${x+rectWidth/2}" y="${y+16}" font-size="10px" fill="#4D4E53" text-anchor="middle">
      ${interfaceName}
    </text>
  </a>`;
}

function lineWithTriangle(x, y, reverse) {
  const length = reverse ? -30 : 30;
  return `
  <line x1="${x}" y1="${y}" x2="${x+length}" y2="${y}" stroke="#D4DDE4""/>
  ${triangle(x, y, reverse)}`;
}

function connectingLineWithTriangle(x, y, reverse) {
  const width = reverse ? -17 : 17;
  return `
  <polyline points="${x},${y} ${x+width},${y} ${x+width},${y+45} ${x},${y+45}" stroke="#D4DDE4" fill="none"/>
  ${triangle(x, y, reverse)}`;
}

function triangle(x, y, reverse) {
  const width = reverse ? -10 : 10;
  return `<polyline points="${x},${y} ${x+width},${y-5} ${x+width},${y+5} ${x},${y}" stroke="#D4DDE4" fill="#fff"/>`;
}

function calculateRectWidth(text) {
  return text.length * 8 < 75 ? 75 : text.length * 8;
}

function moveBy(number, delta, reverse) {
  return number + (reverse ? -delta : delta);
}

function includeInRange(number, start, end) {
  return [
    Math.min(start, number),
    Math.max(end, number)
  ];
}

function drawDiagram(inheritanceChain) {
  let str = '';
  let reverse = false;

  for (let i = 0; i < inheritanceChain.length; i++) {
    const fill = (inheritanceChain[i] == mainInterfaceName) ? '#F4F7F8': '#fff';
    const rectWidth = calculateRectWidth(inheritanceChain[i]);
    // Minumum space required to continue the current row
    let reqSpace = rectWidth;
    if (i > 0) reqSpace += 30;
    // If the rect from the next iteration won't fit in the row, we need to be
    // sure that at least the connectingLineWithTriangle will fit
    if (i < inheritanceChain.length - 1) reqSpace += 17;
    const reqBounds = includeInRange(
      moveBy(xpos, reqSpace, reverse), left, right
    );
    // Will the current drawing items fit inside the viewbox? Subtract the
    // stroke width from the viewbox width to prevent stroke cut off.
    const canContinueRow = reqBounds[1] - reqBounds[0] <= 650 - 2;

    if (i > 0) {
      if (canContinueRow) {
        str += lineWithTriangle(xpos, ypos + 14, reverse);
        xpos = moveBy(xpos, 30, reverse);
      } else {
        str += connectingLineWithTriangle(xpos, ypos + 14, reverse);
        [left, right] = includeInRange(moveBy(xpos, 17, reverse), left, right);
        ypos += 46;
        height += 46;
        reverse = !reverse;
      }
    }

    str += rectWithText(xpos, ypos, fill, inheritanceChain[i], reverse);
    xpos = moveBy(xpos, rectWidth, reverse);
    [left, right] = includeInRange(xpos, left, right);
  }
  return str;
}

let output = '';

if (inheritanceChain.length > 1) {
  let diagram = drawDiagram(inheritanceChain); // needs to run first to calculate left and height
  output = `<svg viewbox="${left-1} -1 650 ${height+2}" preserveAspectRatio="xMinYMin meet">`;
  output += diagram;
  output +='</svg>';
}

%>
<%-output%>
